class RouteMigrator
  ROUTES_HEAP_FILE = 'routes_coll.txt'
  ROUTES_MAP_FILE = 'route_map_2_0.rb'
  NAMED_ACTIONS = %w(edit new)
  EXTENSIONS = %w(rhtml rjs rb)
  NAMED_ROUTES = ActionController::Routing::Routes.named_routes.routes.keys.map { |r| r.to_s }.sort

  # dumps the routes method found in the application code
  # in ROUTES_MAP_FILE
  def self.dump_current_route_methods
    raise "I won't overwrite #{ROUTES_MAP_FILE} delete it if you're sure" if File.exist?(ROUTES_MAP_FILE)
    %x(grep -ir _url app/*|grep -v svn > #{ROUTES_HEAP_FILE})
    %x(grep -ir _path app/*|grep -v svn >> #{ROUTES_HEAP_FILE})
    route_methods = []
    File.open(ROUTES_HEAP_FILE).each do |line|
      route_methods << line.scan(/(\w+\_+path|\w+\_+url)\(| /).delete_if { |m| m == [nil] }
    end
    named_actions = NAMED_ACTIONS.map { |a| "#{a}_" }
    route_methods.flatten!.map! { |m| m.to_s.sub(/^#{named_actions.join('|')}/, '') }
    File.open(ROUTES_MAP_FILE, 'w') do |file|
      file.puts "ROUTE_MAP = {"
      route_methods.uniq.sort.each { |m| file.puts %Q(  "#{m}" => "#{m}",) }
      file.puts "}"
    end
  end

  #the named routes generated from 2.0
  def self.dump_named_routes
    p *NAMED_ROUTES
  end

  def self.route_map
    require ROUTES_MAP_FILE unless defined? ROUTE_MAP
    ROUTE_MAP
  end

  #regexp substitutions
  def self.substitutions
    substitutions = {}
    route_map.each do |original_route, new_route|
      substitutions[original_route] = new_route
      NAMED_ACTIONS.each { |a| substitutions["#{a}_#{original_route}"] = "#{a}_#{new_route}" }
    end
    substitutions
  end

  def self.sed_regexp
    substitutions.map { |original, new| 's/\([^\w_]\)' + original + '/\1' + new + '/g' }
  end

  def self.sed_command_string
    @sed_string ||= "-e " << sed_regexp.map { |r| "'#{r}'" }.join(' -e ')
  end

  #file to be processed
  def self.files
    files = []
    %w(app test).each do |directory|
      files += %x(find #{directory} -regextype posix-awk -iregex "^.*\.(#{EXTENSIONS.join('|')})$").split("\n")
    end
    files
  end

  #checks if the hash in ROUTES_MAP_FILE doesn't include named routes
  #that are not generated from 2.0
  def self.check_new_routes
    invalid_new_routes = []
    route_map.values.each do |r|
      invalid_new_routes.push(r) unless NAMED_ROUTES.member?(r.sub(/_url$|_path$/, ''))
    end
    if !invalid_new_routes.blank?
      p "The following new named routes you've specified seem to be not existent"
      p *invalid_new_routes
      return false
    end
    true
  end

  # upgrades through a search and replace the routes
  def self.upgrade_route_methods!
    raise "check_new_routes failed!!!" unless check_new_routes
    %x(sed -i #{sed_command_string} #{files.join(' ')})
  end

end
